﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Data.OleDb;
using System.Data;
using System.Configuration;
using System.Windows.Forms;

namespace Test2.Model
{
    class DatabaseAccessRepository : iDatabaseRepository
    {
        private OleDbConnection conn = new OleDbConnection(ConfigurationSettings.AppSettings["accessConnString"].ToString());
        
        public DataTable selectUitvoeren(OleDbCommand cmd)
        {
            DataSet ds = new DataSet();
            DataTable dt = new DataTable();
            try
            {
                if (cmd.Connection.State == ConnectionState.Closed) cmd.Connection.Open();
                cmd.ExecuteNonQuery();
                if (cmd.Connection.State == ConnectionState.Open) cmd.Connection.Close();
                OleDbDataAdapter oda = new OleDbDataAdapter();
                oda.SelectCommand = cmd;
                oda.Fill(ds);
                dt = ds.Tables[0];
            }
                            #region Exceptionhandlers
                            catch (System.Data.Odbc.OdbcException ex)
                            {
                                string str = "Source:" + ex.Source + "\n" + "Message:" + ex.Message + "\n" + "Stack Trace:" + ex.StackTrace;
                                Console.WriteLine(str, "Specific Exception");
                                //De user de keuze geven te stoppen
                                DialogResult result = DialogResult.Abort;
                                result = MessageBox.Show("Er kon geen verbinding worden gemaakt met de database.\n\n" + ex.GetType() + ":\n" + ex.Message,
                                                            "Database Error", MessageBoxButtons.AbortRetryIgnore, MessageBoxIcon.Stop);
                                if (result == DialogResult.Abort)
                                {
                                    Application.Exit();
                                }
                            }
                            catch (System.InvalidOperationException ex)
                            {
                                string str = "Source:" + ex.Source + "\n" + "Message:" + ex.Message + "\n" + "Stack Trace:" + ex.StackTrace;
                                Console.WriteLine(str, "Specific Exception");
                            }
                            catch (System.Data.OleDb.OleDbException ex)
                            {
                                string str = "Source:" + ex.Source + "\n" + "Message:" + ex.Message;
                                Console.WriteLine(str, "Database Exception");
                            }
                            catch (System.Exception ex)
                            {
                                string str = "Source:" + ex.Source + "\n" + "Message:" + ex.Message;
                                Console.WriteLine(str, "Generic Exception");
                            }
                            #endregion
            return dt;
        }
        public void insertUitvoeren(OleDbCommand cmd)
        {
            try
            {
                if (cmd.Connection.State == ConnectionState.Closed) cmd.Connection.Open();
                cmd.ExecuteNonQuery();
                if (cmd.Connection.State == ConnectionState.Open) cmd.Connection.Close();
                OleDbDataAdapter oda = new OleDbDataAdapter();
                oda.InsertCommand = cmd;
            }
            #region Exceptionhandlers
            catch (System.Data.Odbc.OdbcException ex)
            {
                string str = "Source:" + ex.Source + "\n" + "Message:" + ex.Message + "\n" + "Stack Trace:" + ex.StackTrace;
                Console.WriteLine(str, "Specific Exception");
                //De user de keuze geven te stoppen
                DialogResult result = DialogResult.Abort;
                result = MessageBox.Show("Er kon geen verbinding worden gemaakt met de database.\n\n" + ex.GetType() + ":\n" + ex.Message,
                                            "Database Error", MessageBoxButtons.AbortRetryIgnore, MessageBoxIcon.Stop);
                if (result == DialogResult.Abort)
                {
                    Application.Exit();
                }
            }
            catch (System.InvalidOperationException ex)
            {
                string str = "Source:" + ex.Source + "\n" + "Message:" + ex.Message + "\n" + "Stack Trace:" + ex.StackTrace;
                Console.WriteLine(str, "Specific Exception");
            }
            catch (System.Data.OleDb.OleDbException ex)
            {
                string str = "Source:" + ex.Source + "\n" + "Message:" + ex.Message;
                Console.WriteLine(str, "Database Exception");
            }
            catch (System.Exception ex)
            {
                string str = "Source:" + ex.Source + "\n" + "Message:" + ex.Message;
                Console.WriteLine(str, "Generic Exception");
            }
            #endregion
        }

        public DataTable getKlanten()
        {
            OleDbCommand cmd = new OleDbCommand("SELECT klantID, voornaam, naam, adres, plaats, postcode, telefoon, email FROM Klanten", conn);
            return selectUitvoeren(cmd);
        }

        public DataTable getKlantenVoornaamNaam()
        {
            OleDbCommand cmd = new OleDbCommand("SELECT klantID, voornaam, naam FROM Klanten", conn);
            return selectUitvoeren(cmd);
        }

        public DataTable getKlantenVoornaamNaamFilter(string input)
        {
            input = input.Replace("'", "''");            // anti injection
            OleDbCommand cmd = new OleDbCommand("SELECT klantID, voornaam, naam FROM Klanten WHERE voornaam LIKE '" + input + "%' OR naam LIKE '" + input + "%'", conn);
            return selectUitvoeren(cmd);
        }

        public DataTable getFacturen()
        {
            OleDbCommand cmd = new OleDbCommand("SELECT factuurID, factuurnummer, datum, opmerkingen FROM Facturen", conn);
            return selectUitvoeren(cmd);
        }

        public DataTable getFacturenByKlantID(int klantID)
        {
            OleDbCommand cmd = new OleDbCommand("SELECT factuurID, factuurnummer, datum, opmerkingen FROM Facturen WHERE klantID = "+klantID, conn);
            return selectUitvoeren(cmd);
        }

        public DataTable getFactuurDetails()
        {
            OleDbCommand cmd = new OleDbCommand("SELECT factuurDetailID, artikelNaam, prijs, btw FROM FactuurDetails", conn);
            return selectUitvoeren(cmd);
        }

        public DataTable getFactuurDetailsByFactuurID(int factuurID)
        {
            OleDbCommand cmd = new OleDbCommand("SELECT factuurDetailID, artikelNaam, prijs, btw FROM FactuurDetails WHERE factuurID = "+ factuurID , conn);
            return selectUitvoeren(cmd);
        }

        public void insertKlant(string voornaam, string naam, string adres, string plaats, short postcode, string telefoon, string email)
        {
            OleDbCommand cmd = new OleDbCommand("INSERT INTO Klanten (voornaam, naam, adres, plaats, postcode, telefoon, email) VALUES (?, ?, ?, ?, ?, ?, ?)", conn);

            cmd.Parameters.Add("@voornaam", OleDbType.VarChar, 50).Value = voornaam;
            cmd.Parameters.Add("@naam", OleDbType.VarChar, 50).Value = naam;
            cmd.Parameters.Add("@adres", OleDbType.VarChar, 50).Value = adres;
            cmd.Parameters.Add("@plaats", OleDbType.VarChar, 50).Value = plaats;
            cmd.Parameters.Add("@postcode", OleDbType.SmallInt).Value = postcode;
            cmd.Parameters.Add("@telefoon", OleDbType.VarChar, 50).Value = telefoon;
            cmd.Parameters.Add("@email", OleDbType.VarChar, 50).Value = email;
            
            insertUitvoeren(cmd);
        }

        public void insertFactuur(int klantID, string factuurnummer, DateTime datum, string opmerkingen, List<FactuurDetail> fds)
        {
            factuurnummer=factuurnummer.Replace("'", "");
            OleDbCommand cmd = new OleDbCommand("INSERT INTO Facturen (klantID, factuurnummer, datum, opmerkingen) VALUES (?, ?, ?, ?)", conn);
            cmd.Parameters.Add("@klantID", OleDbType.Numeric).Value = klantID;
            cmd.Parameters.Add("@factuurnummer", OleDbType.VarChar, 50).Value = factuurnummer;
            cmd.Parameters.Add("@datum", OleDbType.Date).Value = datum;
            cmd.Parameters.Add("@opmerkingen", OleDbType.VarChar, 50).Value = opmerkingen;
            insertUitvoeren(cmd);
            // Concurrency solved want factuurnummer MOET uniek zijn in de databank
            OleDbCommand cmd2 = new OleDbCommand("SELECT factuurID FROM facturen where factuurNummer like '"+factuurnummer+"'", conn);
            if (cmd2.Connection.State == ConnectionState.Closed) cmd2.Connection.Open();
                int id = Int32.Parse(cmd2.ExecuteScalar().ToString());
                if (cmd.Connection.State == ConnectionState.Open) cmd.Connection.Close();
                foreach (FactuurDetail fd in fds)
                {
                    insertFactuurDetails(id, fd.artikelNaam.ToString(), (float)fd.prijs, (byte)fd.btw);
                }
        }

        private void insertFactuurDetails(int factuurID, string artikelNaam, float prijs, byte btw)
        {
            OleDbCommand cmd = new OleDbCommand("INSERT INTO FactuurDetails (factuurID, artikelNaam, prijs, btw) VALUES (?, ?, ?, ?)", conn);
            cmd.Parameters.Add("@factuurID", OleDbType.Numeric).Value = factuurID;
            cmd.Parameters.Add("@artikelNaam", OleDbType.VarChar, 50).Value = artikelNaam;
            cmd.Parameters.Add("@prijs", OleDbType.Currency).Value = prijs;
            cmd.Parameters.Add("@btw", OleDbType.TinyInt).Value = btw;
            insertUitvoeren(cmd);
        }
    }
}
